package com.zhz.common.tool.mybatisplus.base.core.contract;

import com.zhz.common.tool.mybatisplus.base.core.enums.ResultCode;
import com.zhz.common.tool.mybatisplus.base.dal.utils.Converter;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

/**
 * 统一的接口响应,标准的响应数据结构
 *
 * @param <T>
 */
@Data
@AllArgsConstructor
public class R<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 编码：0、请求成功；500、请求成功但服务异常；403、未登录或者token已失效；401、已登录没有权限。
     */
    protected Integer code;
    /**
     * 描述
     */
    protected String message;

    /**
     * 操作是否成功
     */
    protected boolean success=true;


    /**
     * 响应数据
     */
    protected T data;

    public boolean isSucceed() {
        return Objects.equals(this.getCode(), ResultCode.OK.getCode());
    }

    private static final R SUCCESS = new R<>();


    public R(ResultCode code) {
        this.success = code.getSuccess();
        this.code = code.getCode();
        this.message = code.getMessage();
    }

    public R(ResultCode code, T data) {
        this.success = code.getSuccess();
        this.code = code.getCode();
        this.message = code.getMessage();
        this.data = data;
    }

    public R(Integer code, String message, boolean success) {
        this.code = code;
        this.message = message;
        this.success = success;
    }

    public R() {
        this(ResultCode.OK.getCode(), ResultCode.OK.getMessage(),ResultCode.OK.getSuccess());
    }


    public R(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public R(T data) {
        this(ResultCode.OK.getCode(), ResultCode.OK.getMessage(),ResultCode.OK.getSuccess(), data);
    }

    public R(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static <T> R<T> succeed(T payload) {
        return new R(payload);
    }

    public static <T> R<T> ok() {
        return new R<>();
    }

    public static <T> R<T> ok(T payload) {
        return succeed(payload);
    }

    public static <T, D> R<D> ok(T payload, Class<D> target) {
        return succeed(Converter.copy(payload, target));
    }

    public static <T, D> R<List<D>> ok(List<T> payload, Class<D> target) {
        return succeed(Converter.copy(payload, target));
    }

    public static <T> R<T> okWithDesc(String message) {
        return new R(ResultCode.OK.getCode(), message);
    }

    public static <T> R<T> fail() {
        return fail(ResultCode.FAIL.getCode());
    }

    public static <T> R<T> fail(Integer errCode) {
        return new R(ResultCode.FAIL.getCode(), ResultCode.FAIL.getMessage(),ResultCode.FAIL.getSuccess());
    }

    public static <T> R<T> fail(String msg) {
        return fail(ResultCode.FAIL.getCode(), msg);
    }

    public static <T> R<T> fail(Integer errCode, String msg) {
        return new R(ResultCode.FAIL.getCode(), msg,ResultCode.FAIL.getSuccess(),null);
    }

    public static boolean empty(R<?> r) {
        return Objects.isNull(r) || !Objects.equals(r.getCode(), ResultCode.OK.getCode()) || Objects.isNull(r.getData());
    }

    public static <T> R<T> transform(R source) {
        R<T> target = new R();
        target.setCode(source.getCode());
        target.setMessage(source.getMessage());
        target.setSuccess(source.isSuccess());
        return target;
    }


    public boolean isSuccess(){
        return success;
    }
    public boolean isFail(){
        return !success;
    }

}